/*
    file.c.tst - Unit tests for the mprFile module
  
    Copyright (c) All Rights Reserved. See details at the end of the file.
 */

/********************************** Includes **********************************/

#include    "testme.h"
#include    "mpr.h"

/*********************************** Locals **********************************/

#define TESTFILE    ".testFile.tmp"
#define FILEMODE    0644

/************************************ Code ************************************/

static void basicIO()
{
    MprFile         *file;
    MprPath         info;
    MprOff          pos;
    ssize           len, rc;
    char            buf[512];

    rc = mprDeletePath(TESTFILE);
    ttrue(!mprPathExists(TESTFILE, R_OK));
    
    file = mprOpenFile(TESTFILE, O_CREAT | O_TRUNC | O_RDWR, FILEMODE);
    ttrue(file != 0);
    ttrue(mprPathExists(TESTFILE, R_OK));

    len = mprWriteFile(file, "abcdef", 6);
    ttrue(len == 6);
    mprCloseFile(file);

    ttrue(mprPathExists(TESTFILE, R_OK));
    rc = mprGetPathInfo(TESTFILE, &info);
    ttrue(rc == 0);

#if ME_WIN_LIKE
    /*
        On windows, the size reflects the size on disk and is not updated until actually save to disk.
     */
#else
    ttrue(info.size == 6);
    ttrue(!info.isDir);
    ttrue(info.isReg);
#endif
    
    file = mprOpenFile(TESTFILE, O_RDWR, FILEMODE);
    ttrue(file != 0);

    pos = mprSeekFile(file, SEEK_SET, 1);
    len = mprReadFile(file, buf, sizeof(buf));
    ttrue(len == 5);
    buf[len] = '\0';
    
    ttrue(strcmp(buf, "bcdef") == 0);

    pos = mprSeekFile(file, SEEK_SET, 0);
    ttrue(pos == 0);
    ttrue(mprGetFilePosition(file) == 0);

    len = mprWriteFileString(file, "Hello\nWorld\n");
    ttrue(len == 12);
    mprSeekFile(file, SEEK_SET, 0);

    rc = mprReadFile(file, buf, sizeof(buf));
    ttrue(rc == 12);
    ttrue(mprGetFilePosition(file) == 12);
    buf[12] = '\0';
    ttrue(strcmp(buf, "Hello\nWorld\n") == 0);
    mprCloseFile(file);

    rc = mprDeletePath(TESTFILE);
    ttrue(!mprPathExists(TESTFILE, R_OK));
}
    

static void bufferedIO()
{
    MprFile         *file;
    MprPath         info;
    ssize           len;
    char            *str;
    int             rc, c;

    rc = mprDeletePath(TESTFILE);
    ttrue(!mprPathExists(TESTFILE, R_OK));
    
    file = mprOpenFile(TESTFILE, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, FILEMODE);
    if (file == 0) {
        ttrue(file != 0);
        return;
    }
    ttrue(mprPathExists(TESTFILE, R_OK));
    
    mprEnableFileBuffering(file, 0, 512);
    
    len = mprWriteFile(file, "abc", 3);
    ttrue(len == 3);
    
    len = mprPutFileChar(file, 'd');
    ttrue(len == 1);
    
    len = mprPutFileString(file, "ef\n");
    ttrue(len == 3);
    
    ttrue(mprPathExists(TESTFILE, R_OK));
    
    /*
        No data flushed yet so the length should be zero
     */
    rc = mprGetPathInfo(TESTFILE, &info);
    ttrue(rc == 0);
    ttrue(info.size == 0);
    
    rc = mprFlushFile(file);
    ttrue(rc == 0);
    mprCloseFile(file);
    
    /*
        Now the length should be set
     */
    rc = mprGetPathInfo(TESTFILE, &info);
    ttrue(rc == 0);

    /*
        TODO windows seems to delay setting this
     */
    if (info.size != 7) {
        mprSleep(2000);
        rc = mprGetPathInfo(TESTFILE, &info);
    }
    ttrue(info.size == 7);

    file = mprOpenFile(TESTFILE, O_RDONLY | O_BINARY, FILEMODE);
    ttrue(file != 0);
    
    mprSeekFile(file, SEEK_SET, 0);
    ttrue(mprPeekFileChar(file) == 'a');
    c = mprGetFileChar(file);
    ttrue(c == 'a');
    str = mprReadLine(file, 0, NULL);
    ttrue(str != 0);
    len = strlen(str);
    ttrue(len == 5);   
    ttrue(strcmp(str, "bcdef") == 0);
    mprCloseFile(file);

    mprDeletePath(TESTFILE);
    ttrue(!mprPathExists(TESTFILE, R_OK));
}
    

#if KEEP
/*
    Make a unique filename for a given thread
 */
static char *makePath(cchar *name)
{
    char    *path;

    if ((path = sfmt("%s-%d-%s", name, getpid(), mprGetCurrentThreadName())) == 0) {
        return 0;
    }
    return path;
}
#endif


int main(int argc, char **argv)
{
    mprCreate(argc, argv, 0);
    mprDeletePath(TESTFILE);
    basicIO();
    bufferedIO();
    mprDeletePath(TESTFILE);
    return 0;
}


/*
    @copy   default

    Copyright (c) Embedthis Software. All Rights Reserved.

    This software is distributed under commercial and open source licenses.
    You may use the Embedthis Open Source license or you may acquire a 
    commercial license from Embedthis Software. You agree to be fully bound
    by the terms of either license. Consult the LICENSE.md distributed with
    this software for full details and other copyrights.

    Local variables:
    tab-width: 4
    c-basic-offset: 4
    End:
    vim: sw=4 ts=4 expandtab

    @end
 */
